#include "include/global.h"
#include "include/type.h"
#include "include/kconst.h"
#include "include/sysdescriptor.h"
#include "include/klib.h"
#include "include/proc.h"

u32 seg2phys(u16 seg)
{
	DESCRIPTOR* p_dest = &gdt[seg >> 3];
	return (p_dest->base_high<<24 | p_dest->base_mid<<16 | p_dest->base_low);
}

void init_descriptor(DESCRIPTOR *p_desc,u32 base,u32 limit,u16 attribute)
{
	p_desc->limit_low	= limit & 0x0FFFF;
	p_desc->base_low	= base & 0x0FFFF;
	p_desc->base_mid	= (base >> 16) & 0x0FF;
	p_desc->attr1		= attribute & 0xFF;
	p_desc->limit_high_attr2= ((limit>>16) & 0x0F) | (attribute>>8) & 0xF0;
	p_desc->base_high	= (base >> 24) & 0x0FF;
}

void gdtcpy()
{
    memcpy( &gdt,
            (void*)(*((u32*)(&gdt_ptr[2]))),
            *((u16*)(&gdt_ptr[0])) + 1
           );

    //设置gdt_ptr
    u16* p_gdt_limit = (u16*)(&gdt_ptr[0]);
	u32* p_gdt_base  = (u32*)(&gdt_ptr[2]);
	*p_gdt_limit = GDT_SIZE * sizeof(DESCRIPTOR) - 1;
	*p_gdt_base  = (u32)&gdt;
    //设置TSS
    memset(&tss, 0, sizeof(tss));
    tss.ss0 = SELECTOR_FLATRW;
    init_descriptor(&gdt[INDEX_TSS], vir2phys(seg2phys(SELECTOR_FLATRW), &tss), sizeof(tss) - 1, DA_386TSS);
    tss.iobase = sizeof(tss);

    PROCESS* p_proc = proc_table;
    u16 selector_ldt = SELECTOR_LDT_FIRST;
    for (int i = 0; i < PROC_SZ; i++)
    {
        init_descriptor(&gdt[selector_ldt>>3], vir2phys(seg2phys(SELECTOR_FLATRW), p_proc->ldts), LDT_SIZE * sizeof(DESCRIPTOR), DA_LDT);
        p_proc++;   
        selector_ldt += 1 << 3;
    }

}